#include "SpriteManager.hpp"

#include <iostream>
#include <sstream>
#include <cstring>

#include "Utils.hpp"

SpriteManager::SpriteParam::SpriteParam(const std::string& spriteName, int angle)
            :name(spriteName),angle(angle)
{
    std::stringstream idBuilder; // Contructor for complete id name
    idBuilder << spriteName;
    idBuilder << "_" << angle;
    completeIdName = idBuilder.str();

    // std::cout << "CompleteIdName: " << completeIdName << std::endl;
}

SpriteManager::SpriteManager()
{

}

SpriteManager::~SpriteManager()
{

}

bool SpriteManager::loadSpriteFile(const std::string& fileName, int centerX, int centerY)
{
    // Check if we already got this file
    if ( this->exist(fileName) )
    {
        return true;
    }

    sf::Image img;
    if ( !img.LoadFromFile(fileName) )
    {
        std::cerr << "File to load '" << fileName << "'" << std::endl;
        return false;
    }

    img.SetSmooth(false);
    img.CreateMaskFromColor(sf::Color(255, 0, 255));
    // img.SetSmooth(true);
    m_bank[fileName] = CenteredSprite(&img,0,13);

    std::cout << "Sprite loaded: '" << fileName << "'" << std::endl;

    return true;
}

bool SpriteManager::loadSprite(const std::string& fileName, int centerX, int centerY,bool mipmap)
{
    bool bResult = true;

    if ( mipmap )
    {
        for ( unsigned int i = 0 ; i < 7 ; i++ )
        {
            std::stringstream idBuilder; // Contructor for complete id name
            idBuilder << i+1;

            char* pSpriteName = new char[fileName.size() + idBuilder.str().size() + 2];

            strncpy(pSpriteName,fileName.data(),fileName.size()-4);
            pSpriteName[fileName.size()-4] = '\0';
            strcat(pSpriteName,"_");
            strcat(pSpriteName,idBuilder.str().c_str());
            strcat(pSpriteName,".png");

            bResult &= this->loadSpriteFile(pSpriteName,centerX,centerY);

            delete [] pSpriteName;
        }
    }
    else
    {
        bResult &= this->loadSpriteFile(fileName,centerX,centerY);
    }

    return bResult;
}

bool SpriteManager::loadSimpleSprite(const std::string& fileName)
{
    SpriteParam spriteInfo(fileName,0);

    std::map<SpriteParam, sf::Sprite, SpriteParamComp>::const_iterator itElem = m_bucket.find(spriteInfo);
    // Check if we already got this file
    if ( itElem != m_bucket.end() )
    {
        return true;
    }

    sf::Image img;
    if ( !img.LoadFromFile(fileName) )
    {
        std::cerr << "File to load '" << fileName << "'" << std::endl;
        return false;
    }

    img.SetSmooth(false);
    img.CreateMaskFromColor(sf::Color(255, 0, 255));
    m_bank[fileName] = CenteredSprite(&img,img.GetWidth()/2,img.GetHeight()/2);

    sf::Sprite sprite;
    sprite.SetImage(img);
    sprite.SetCenter(img.GetWidth()/2,img.GetHeight()/2);

    m_bucket[spriteInfo] = sprite;

    return true;
}

bool SpriteManager::exist(const std::string& fileName)const
{
    std::map<std::string, CenteredSprite>::const_iterator itElem = m_bank.find(fileName);
    if ( itElem != m_bank.end() )
    {
        return true;
    }

    return false;
}

void SpriteManager::generateBucket()
{
    for ( std::map<std::string,CenteredSprite>::const_iterator itImage = m_bank.begin() ; itImage != m_bank.end() ; ++itImage )
    {
        sf::Sprite sprite;
        sprite.SetImage(itImage->second.image);
        sprite.SetCenter(itImage->second.centerX,itImage->second.centerY);
        for ( unsigned int angle = 0 ; angle < 360 ; angle++ )
        {
            sprite.Rotate(1);
            SpriteParam spriteInfo(itImage->first,angle);

            m_bucket[spriteInfo] = sprite;
        }
    }
}

const sf::Sprite& SpriteManager::getSprite(const std::string& fileName)const
{
    SpriteParam spriteInfo(fileName,0);

    std::map<SpriteParam, sf::Sprite, SpriteParamComp>::const_iterator itElem = m_bucket.find(spriteInfo);
    if ( itElem == m_bucket.end() )
    {
        std::cerr << "Sprite not found with '" << fileName << std::endl;
    }

    return itElem->second;
}

const sf::Sprite& SpriteManager::getSprite(const std::string& fileName, int angle, int level)const
{
    std::stringstream idBuilder; // Contructor for complete id name
    idBuilder << level+1;
    char* pSpriteName = new char[fileName.size() + idBuilder.str().size() + 2];

    strncpy(pSpriteName,fileName.data(),fileName.size()-4);
    pSpriteName[fileName.size()-4] = '\0';
    strcat(pSpriteName,"_");
    strcat(pSpriteName,idBuilder.str().c_str());
    strcat(pSpriteName,".png");

    SpriteParam spriteInfo(pSpriteName,Utils::normaliseAngle(angle));
    //  bResult &= this->loadSpriteFile(pSpriteName,centerX,centerY);

    delete [] pSpriteName;




    // SpriteParam spriteInfo(idBuilder.str(),Utils::normaliseAngle(angle));

    std::map<SpriteParam, sf::Sprite, SpriteParamComp>::const_iterator itElem = m_bucket.find(spriteInfo);
    if ( itElem == m_bucket.end() )
    {
        std::cerr << "Sprite not found with '" << fileName << "' Angle: " << angle << " Level: " << level << std::endl;
    }

    return itElem->second;
}
